package net.koodar.forge.system.role.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import net.koodar.forge.mybatis.util.PageUtil;
import net.koodar.forge.system.menu.model.entity.Menu;
import net.koodar.forge.system.menu.manager.MenuManager;
import net.koodar.forge.system.role.model.dto.RoleParamDTO;
import net.koodar.forge.system.role.model.dto.RoleQueryDTO;
import net.koodar.forge.system.role.model.entity.Role;
import net.koodar.forge.system.role.model.entity.RoleMenu;
import net.koodar.forge.system.role.model.vo.RoleVO;
import net.koodar.forge.system.role.manager.RoleManager;
import net.koodar.forge.common.code.UserErrorCode;
import net.koodar.forge.common.domain.dto.MultiResponse;
import net.koodar.forge.common.domain.dto.Response;
import net.koodar.forge.common.domain.dto.SingleResponse;
import net.koodar.forge.common.utils.BeanUtil;
import net.koodar.forge.system.role.manager.RoleMenuManager;
import net.koodar.forge.system.role.service.assembler.RoleAssembler;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author liyc
 */
@Service
@RequiredArgsConstructor
public class RoleService {

	private final RoleManager roleManager;
	private final MenuManager menuManager;
	private final RoleMenuManager roleMenuManager;
	private final RoleAssembler roleAssembler;

	public Response listRole() {
		return MultiResponse.ok(roleManager.list().stream().map(roleAssembler::convertToRoleVo).collect(Collectors.toList()));
	}

	public Response pageBy(RoleQueryDTO roleQueryDTO) {
		Assert.notNull(roleQueryDTO, "Role query must not be null");
		Page<Role> rolePage = roleManager.page(roleQueryDTO.toPage(), roleQueryDTO.toQueryWrapper());
		List<RoleVO> records = rolePage.getRecords().stream().map(roleAssembler::convertToRoleVo).toList();
		return SingleResponse.ok(PageUtil.toPage(records, rolePage.getTotal()));
	}

	public Response getRoleInfo(Long id) {
		Role role = roleManager.findById(id);
		return SingleResponse.ok(roleAssembler.convertToRoleVo(role));
	}

	public Response addRole(RoleParamDTO roleParamDTO) {
		Role optionalRole = roleManager.findByCode(roleParamDTO.getCode());
		if (optionalRole != null) {
			return Response.error(UserErrorCode.ALREADY_EXIST, String.format("角色编码 [%s] 已存在，请更换后再试吧。", roleParamDTO.getCode()));
		}
		Role role = BeanUtil.copy(roleParamDTO, new Role());;
		// 保存角色
		roleManager.save(role);

		// 保存角色和权限信息
		List<Menu> menus = menuManager.listByName(roleParamDTO.getPermissions());
		List<RoleMenu> roleMenus = menus.stream().map(menu -> new RoleMenu(role.getId(), menu.getId())).collect(Collectors.toList());
		roleMenuManager.saveBatch(roleMenus);
		return Response.ok();
	}

	public Response updateRole(RoleParamDTO roleParamDTO) {
		Role role = roleManager.findById(roleParamDTO.getId());
		if (role == null) {
			return Response.error(UserErrorCode.DATA_NOT_EXIST, String.format("角色id [%s] 不存在。", roleParamDTO.getId()));
		}
		Role roleOptional = roleManager.findByCode(role.getCode());
		if (roleOptional != null && !roleOptional.getId().equals(role.getId())) {
			return Response.error(UserErrorCode.ALREADY_EXIST, String.format("角色编码 [%s] 已存在，请更换后再试吧。", roleParamDTO.getCode()));
		}
		roleAssembler.convertToRole(role, roleParamDTO);
		// 保存角色
		roleManager.save(role);

		List<RoleMenu> menus = roleMenuManager.findByRoleId(roleParamDTO.getId());
		roleMenuManager.removeBatchByIds(menus);

		// 保存角色和权限信息
		List<Menu> newMenus = menuManager.listByName(roleParamDTO.getPermissions());
		List<RoleMenu> roleMenus = newMenus.stream().map(menu -> new RoleMenu(role.getId(), menu.getId())).collect(Collectors.toList());
		roleMenuManager.saveBatch(roleMenus);
		return Response.ok();
	}

	public Response deleteRole(Long id) {
		roleManager.deleteRole(id);
		return Response.ok();
	}


}
